package com.open.chat.server.service;

import java.util.List;

import org.jim.core.ImChannelContext;
import org.jim.core.ImConst;
import org.jim.core.ImSessionContext;
import org.jim.core.ImStatus;
import org.jim.core.cache.redis.RedisCacheManager;
import org.jim.core.config.ImConfig;
import org.jim.core.message.MessageHelper;
import org.jim.core.packets.ChatBody;
import org.jim.core.packets.ChatType;
import org.jim.core.packets.Command;
import org.jim.core.packets.RespBody;
import org.jim.core.packets.User;
import org.jim.core.packets.UserStatusType;
import org.jim.core.utils.JsonKit;
import org.jim.server.command.handler.extend.pojo.ReCallReqBody;
import org.jim.server.command.handler.extend.utils.SystemNotify;
import org.jim.server.command.handler.extend.utils.SystemNotify.Operation;
import org.jim.server.config.ImServerConfig;
import org.jim.server.processor.chat.ReCallCmdProcessor;
import org.jim.server.protocol.AbstractProtocolCmdProcessor;
import org.jim.server.util.ChatKit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.open.chat.server.common.redis.CommonKey;

import cn.hutool.core.date.DateUtil;

/**
 * 系统撤回消息
 * @author 刘玉星
 * TODO 
 */
public class ReCallMessageServiceProcessor extends AbstractProtocolCmdProcessor implements ReCallCmdProcessor{
	private static Logger log = LoggerFactory.getLogger(ReCallMessageServiceProcessor.class);
	
	
	@Override
	public RespBody reCall(ReCallReqBody body, ImChannelContext imChannelContext) {
		RespBody respBody = new RespBody(Command.COMMAND_SYS_NOTIFY_RESP,ImStatus.C2001);
		ImSessionContext imSessionContext = imChannelContext.getSessionContext();
		User clientUser = imSessionContext.getImClientNode().getUser();
		if(!clientUser.getUserId().equals(body.getFrom())) {
			return respBody.setCode(ImStatus.C2002.getCode()).setMsg("非法撤销操作");
		}
		ImServerConfig imServerConfig = ImConfig.Global.get();
		MessageHelper messageHelper = imServerConfig.getMessageHelper();
		//如果是公聊
		if(ChatType.CHAT_TYPE_PUBLIC.getNumber() == body.getChatType()) {
			//离线消息删除 、 群组消息删除
			String groupId = body.getTo();
			String pushKey = ImConst.GROUP+CommonKey.SUFFIX+groupId+CommonKey.SUFFIX+body.getFrom();
			//离线
			boolean pushStatus = reCallMsg(ImConst.PUSH,pushKey,body.getMsgId());
			
			String storeKey =  ImConst.GROUP+CommonKey.SUFFIX+groupId;
			//存储
			boolean storeStatus = reCallMsg(ImConst.STORE,storeKey,body.getMsgId());
			
			//撤回了
			if(storeStatus) {
				
				//谁发的消息
				User user = messageHelper.getUserByType(body.getFrom(), UserStatusType.ALL.getNumber());
				//发送通知，通知到人,携带消息ID
				JSONObject js = new JSONObject();
				js.put("data", body);
				SystemNotify.notifyGroup(groupId, "", String.format("%s撤回了一条消息", user.getNick()),Operation.oper_recall_msg,js);
				return respBody;
			}else {
				return respBody.setCode(ImStatus.C2002.getCode()).setMsg("撤销失败");
			}
			
		}
		
		//如果是私聊，需要撤销Store-user和push-user的消息  
		if(ChatType.CHAT_TYPE_PRIVATE.getNumber() == body.getChatType()) {
			//ImConst.PUSH + CommonKey.SUFFIX + ImConst.USER + CommonKey.SUFFIX + userId + CommonKey.SUFFIX + fromUserId
			//离线消息删除 
			String pushKey = ImConst.USER+CommonKey.SUFFIX+body.getTo()+CommonKey.SUFFIX+body.getFrom();
			//离线
			boolean pushStatus = reCallMsg(ImConst.PUSH,pushKey,body.getMsgId());
			
			//存储
			String storeKey =  ImConst.USER+CommonKey.SUFFIX+ChatKit.sessionId(body.getFrom(), body.getTo());
			boolean storeStatus = reCallMsg(ImConst.STORE,storeKey,body.getMsgId());
			
			if(storeStatus) {
				User from = messageHelper.getUserByType(body.getFrom(), UserStatusType.ALL.getNumber());
				//通知到对方和自己,携带消息ID
				JSONObject js = new JSONObject();
				js.put("data", body);
				
				SystemNotify.notifyUser(body.getTo(), "", "您撤回了一条消息",Operation.oper_recall_msg,js);
				SystemNotify.notifyUser(body.getFrom(), "", String.format("%s撤回了一条消息", from.getNick()),Operation.oper_recall_msg,js);
				return respBody;
			}else {
				return respBody.setCode(ImStatus.C2002.getCode()).setMsg("撤销失败");
			}
			
			
			
		}
		return respBody.setCode(ImStatus.C2002.getCode()).setMsg("撤销未知异常");
	}
	
	
	private boolean reCallMsg(String cacheName,String key,String msgId){
		boolean status = false;
		//取反(我觉得300条就顶天了） Double.MAX_VALUE
		List<String> list = RedisCacheManager.getCache(cacheName).sortSetReverseGetAll(key, 0, Double.MAX_VALUE,0,300);
		//List<ChatBody> dataList = JsonKit.toArray(list, ChatBody.class);
		for(String  str : list) {
			ChatBody chat = JsonKit.toBean(str, ChatBody.class);
			if(chat.getId().equals(msgId)) {
				//计算时间超过2分钟就算失败
				Long now = DateUtil.current();
				Long  diff =  (now - chat.getCreateTime())/1000;
				log.info("撤回消息时间差:{}",diff);
				//5分钟
				if(diff - 300 < 0) {
					RedisCacheManager.getCache(cacheName).sorSetRemove(key, str);
					status = true;
				}
				
				break;
			}
			
		}
		return status;
	}

}
